package cn.edu.seu.herald.informationplatform.filter;

import java.io.IOException;
import java.sql.SQLException;
import java.util.List;
import java.util.Map;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import cn.edu.seu.herald.informationplatform.bean.league.Activity;
import cn.edu.seu.herald.informationplatform.bean.league.Linked;
import cn.edu.seu.herald.informationplatform.dao.database.ActivityDao;

public class LeagueActivitiesRequired implements Filter {
	
	private static final String ACTIVITIES_ID = "activities";
	
	private static final String PARAM_NAME_OF_PAGE = "page";
	
	private static final String PARAM_NAME_OF_CONTENT = "content";
	
	private static final String VALUE_OF_HOT_CONTENT = "hot";
	
	private static final String ATTR_NAME_OF_MAX_PAGE = "maxPage";
	
	private static final int MAX_ENTRY_PER_PAGE = 4;
	
	private static final int DEFAULT_PAGE_NUM = 1;
	
	private ActivityDao _activityDao;
	
	private static List<Linked<Activity>> parseToLinkedActivities(
				Map<Integer, Activity> activityMapping, int leagueId) {
		LinkedActivityAdapter adapter =
				LinkedActivityAdapter.getInstance();
		List<Linked<Activity>> activities =
				adapter.adapt(activityMapping);
		return activities;
	}
	
	private static Map<Integer, Activity> getActivityMapping(
			int leagueId, int currentPageNum, String content) throws SQLException {
		int offset = (currentPageNum - 1) * MAX_ENTRY_PER_PAGE;
		int row = MAX_ENTRY_PER_PAGE;
		ActivityDao access = ActivityDao.getDao();
		
		if (content == null || !content.equals(VALUE_OF_HOT_CONTENT)) {
			Map<Integer, Activity> newActivities =
					access.getNewActivitiesByLimitAndLeagueId(leagueId, offset,
							row);
			return newActivities;
		}
		
		Map<Integer, Activity> topActivities =
				access.getHotActivitiesByLimitAndLeagueId(leagueId, offset,
						row);
		return topActivities;
	}

	@Override
	public void init(FilterConfig config) throws ServletException {
		_activityDao = ActivityDao.getDao();
	}

	@Override
	public void destroy() {}

	@Override
	public void doFilter(ServletRequest request,
			ServletResponse response, FilterChain chain)
					throws IOException, ServletException {
		
		HttpServletRequest httpRequest = (HttpServletRequest) request;
		HttpServletResponse httpResponse = (HttpServletResponse) response;

		try {
			int leagueId = getLeagueId(httpRequest);
			int maxPageNum = getMaxPageNum(leagueId);
			httpRequest.setAttribute(ATTR_NAME_OF_MAX_PAGE, maxPageNum);
			int currentPageNum = getPage(httpRequest, maxPageNum);
			String content = httpRequest.getParameter(PARAM_NAME_OF_CONTENT);
		
			Map<Integer, Activity> activityMapping =
					getActivityMapping(leagueId, currentPageNum, content);
			List<Linked<Activity>> activities =
					parseToLinkedActivities(activityMapping, leagueId);
			request.setAttribute(ACTIVITIES_ID, activities);
		} catch (SQLException e) {
			httpResponse.sendError(404, "LeagueActivitiesRequired");
			return;
		}
		
		chain.doFilter(request, response);
	}
	
	private int getLeagueId(HttpServletRequest httpRequest) {
		String leagueIdParam = httpRequest.getParameter(
				LeagueSpecified.PARAM_NAME_OF_LEAGUE_ID);
		return Integer.parseInt(leagueIdParam);
	}
	
	private int getMaxPageNum(int leagueId) throws SQLException {
		int numOfActivities = _activityDao.getNumOfActivitiesByLeagueId(
				leagueId);
		return (numOfActivities + MAX_ENTRY_PER_PAGE - 1)
				/ MAX_ENTRY_PER_PAGE;

	}

	private int getPage(HttpServletRequest httpRequest,
			int maxPageNum) {
		String attrPage = httpRequest.getParameter(PARAM_NAME_OF_PAGE);
		
		if (attrPage == null) {
			return DEFAULT_PAGE_NUM;
		}
		
		try {
			int page = Integer.valueOf(attrPage);
			if (page > maxPageNum || page <= 0) {
				page = DEFAULT_PAGE_NUM;
			}
			return page;
		} catch (NumberFormatException e) {
			return DEFAULT_PAGE_NUM;
		}
	}

}
